//! Copyright 2012 Xicut Technology, Inc.
//! All rights reserved
//!
#include "HostCmd.h"
#include "AT25DF041.h"
#include "Counter.h"
#include "StrLib.h"
#include "User.h"
#include "Rtc.h"


void cHostCmd::InitReset()
{
}


U8 cHostCmd::GenerateReply(U8 *pData, U8 iRpl, U8 iErrCode)
{
    // STX
    pData[0] = 0x02;
    pData [ID_INDEX] = DEFAULT_ID_HIGH;
    pData [ID_INDEX+1] = DEFAULT_ID_LOW;
    // rpl
    pData[CMD_INDEX] = iRpl;

    // Total User
    cStrLib::WordToDecStr(&pData[DATA_INDEX], cUser::GetTotalUser());

    // error code
    pData[DATA_INDEX + 4] = iErrCode;

    //check sum
    U8 cs = 0;
    for (U8 i=ID_INDEX; i<DATA_INDEX + 5; i++)
    {
        cs += pData[i];
    }
    cStrLib::ByteToHexStr(&pData[DATA_INDEX + 5], cs);

    pData[DATA_INDEX + 7] = 0x0D;

    return (DATA_INDEX + 8);
}


U8 cHostCmd::GenerateReply(U8 *pData, U8 iRpl, U8 iErrCode, U8 *pDataRpl, U8 iDataRplLength)
{
    // STX
    pData[0] = 0x02;

    // rpl
    pData[CMD_INDEX] = iRpl;

    // Total User
    cStrLib::WordToDecStr(&pData[DATA_INDEX], cUser::GetTotalUser());

    // error code
    pData[DATA_INDEX+4] = iErrCode;

    cStrLib::Strcpy(&pData[DATA_INDEX+5], pDataRpl, iDataRplLength);

    //check sum
    U8 cs = 0;
    for (U8 i=ID_INDEX; i<(iDataRplLength + DATA_INDEX + 5); i++)
    {
        cs += pData[i];
    }
    cStrLib::ByteToHexStr(&pData[(iDataRplLength + DATA_INDEX + 5)], cs);

    pData[(iDataRplLength + DATA_INDEX + 7)] = 0x0D;

    return (iDataRplLength + DATA_INDEX + 8);
}


U16 cHostCmd::CmdProcessor(U8 *pData, U16 iLen)
{
    U16 tempReturn = iLen;
    U8 pCard[7];

    switch (pData[CMD_INDEX])
    {
    case CREATE_USER_CMD:
        {
            cStrLib::StrToStrHex(pCard, &pData[DATA_INDEX], 14);
            cUser::Register(pCard);
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case ERASE_USER_CMD:
        {
            cStrLib::StrToStrHex(pCard, &pData[DATA_INDEX], 14);
            cUser::Erase(pCard);
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case ERASE_ALL_USER_CMD:
        {
            cUser::EraseAll();
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case CHECK_USER_CMD:
        {
            cStrLib::StrToStrHex(pCard, &pData[DATA_INDEX], 14);
            U32 cardCode = 0;
			U16 timeZone = 0;
			U16 userID = 0;

            cardCode = ( (((U32)pCard[0]) << 24) | (((U32)pCard[1]) << 16) | (((U32)pCard[2]) << 8) | ((U32)pCard[3]) );
            if (true == cUser::FindUser(cardCode, timeZone, userID))
            {
                tempReturn = GenerateReply(pData, 'A', '0');
            }
            else
            {
                tempReturn = GenerateReply(pData, 'N', '1');
            }
        } break;

    case READ_TOTAL_USER_CMD:
        {
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case TIME_LED_OFF_CMD:
        {
            cCounter::SetLedOffTime(cStrLib::StrDecToByte(&pData[DATA_INDEX]));
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case SET_COUNTER_CMD:
        {
            cCounter::SetCounter(cStrLib::StrDecToWord(&pData[DATA_INDEX]));
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case READ_COUNTER_CMD:
        {
            U8 pcounter[4];
            cStrLib::WordToDecStr(pcounter, cCounter::GetCounter());
            tempReturn = GenerateReply(pData, 'A', '0', pcounter, 4);
        } break;

    case GET_TIME_CMD:
        {
            U8 time[12];
            cStrLib::StrDecToStr(time, cRtc::GetTimeAsStr(), 6);
            tempReturn = GenerateReply(pData, 'A', '0', time, 12);
        } break;

    case SET_TIME_CMD:
        {
            U8 time[6];
            cStrLib::StrToStrDec(time, &pData[DATA_INDEX], 12);
            cRtc::SetTimeAsStr(time);
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;

    case GET_TIME_POINT_CMD:
        {
            U8  timePoint[6];
            U16 temp = cCounter::GetTimeZone(cStrLib::StrDecToByte(&pData[DATA_INDEX]));
            if (0xFFFF == temp)
            {
                timePoint[0] = 'F';
                timePoint[1] = 'F';
                timePoint[2] = 'F';
                timePoint[3] = 'F';
                timePoint[4] = 'F';
                timePoint[5] = 'F';
            }
            else
            {
                cStrLib::ByteToStrDec(timePoint, temp/60);
                cStrLib::ByteToStrDec(&timePoint[2], temp%60);
                timePoint[4] = '0';
                timePoint[5] = '0';
            }

            tempReturn = GenerateReply(pData, 'A', '0', timePoint, 6);
        } break;

    case SET_TIME_POINT_CMD:
        {
            if (true == cStrLib::StrCmpWithConst(&pData[DATA_INDEX+2], 'F', 6))
            {
                //cCounter::SetTimeZone(cStrLib::StrDecToByte(&pData[DATA_INDEX]), 0xFFFF);
            }
            else
            {
                //cCounter::SetTimeZone(cStrLib::StrDecToByte(&pData[DATA_INDEX]), ((U16)cStrLib::StrDecToByte(&pData[DATA_INDEX+2]))*60 + cStrLib::StrDecToByte(&pData[DATA_INDEX+2+2]));
            }
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;
#if 0
    case TEST_REGISTER_USER_CMD:
        {
            pCard[0] = 0x00;
            pCard[1] = 0x00;
            pCard[2] = 0x00;
            pCard[3] = 0x5A;
            pCard[4] = 0xA5;
            pCard[5] = 0x55;
            pCard[6] = 0xAA;

            for (U16 i=0; i<2000; i++)
            {
                pCard[0] = (U8)(i>>8);
                pCard[1] = (U8)(i);
                cUser::Register(pCard);
            }

            pCard[0] = 0x00;
            pCard[1] = 0x00;
            pCard[2] = 0x00;
            pCard[3] = 0x5A;
            pCard[4] = 0xA5;
            pCard[5] = 0x55;
            pCard[6] = 0xAA;

            for (U16 i=0; i<2000; i++)
            {
                pCard[0] = (U8)(i>>8);
                pCard[1] = (U8)(i);
                if (false == cUser::FindUser(pCard))
                {
                    tempReturn = GenerateReply(pData, 'N', '1');
                    break;
                }
            }
            tempReturn = GenerateReply(pData, 'A', '0');
        } break;
#endif

    default:
        {
            tempReturn = GenerateReply(pData, 'N', '3');
        } break;
    }

    return (tempReturn);
}
